#include "ConfigModule.h"
#include <iostream>
#include "Depends/RapidXML/rapidxml.hpp"
#include "Depends/RapidXML/rapidxml_iterators.hpp"
#include "Depends/RapidXML/rapidxml_print.hpp"
#include "Depends/RapidXML/rapidxml_utils.hpp"

FragrantGrass::ConfigModule::ConfigModule(IPluginManager* p)
{
	m_pPluginManager = p;
	m_strConfigPath = m_pPluginManager->GetConfigPath();
	m_fileParserMap.clear();
	m_pkLogModule = NULL;
	m_ServerInfoReportList.Clear();
}

FragrantGrass::ConfigModule::~ConfigModule()
{
	m_pPluginManager = NULL;
	m_ServerInfoReportList.clear_server_list();
	m_ServerInfoReportList.Clear();
}

bool FragrantGrass::ConfigModule::Init()
{
	m_pkLogModule = m_pPluginManager->FindModule<ILogModule>();
	RegisterFileParser(FileParseType::FPT_SERVER_DATA, std::bind(&ConfigModule::FileParser_ServerDatas, this, std::placeholders::_1, std::placeholders::_2), "Servers.xml");

	return true;
}

bool FragrantGrass::ConfigModule::AfterInit()
{
	if (!GetConfigDatas(FileParseType::FPT_SERVER_DATA))
	{
		return false;
	}
	return true;
}

bool FragrantGrass::ConfigModule::Finalize()
{
	m_fileParserMap.clear();
	m_pkLogModule = NULL;
	m_ServerInfoReportList.Clear();
	return true;
}

void FragrantGrass::ConfigModule::SetConfigPath(const std::string& strPath)
{
	m_strConfigPath = strPath;
}

void* FragrantGrass::ConfigModule::GetConfigDatas(FileParseType type)
{
	FileParserMap::iterator it = m_fileParserMap.find(type);
	if (it == m_fileParserMap.end())
	{
		std::ostringstream stream;
		stream << "[ConfigModule] FileParseType " << (int)type;
		stream << "Has No corresponding to Parser" << std::endl;
		m_pkLogModule->LogDebug(stream, __FUNCTION__, __LINE__);
		return NULL;
	}

	FILE_PARSE_FUNCTION& rkParser = it->second.function;
	std::string strConfigName = it->second.name;
	std::string strContent;

	if (it->second.existed)
	{
		return rkParser(strConfigName, strContent);
	}

#ifdef FG_DEBUG_MODE
	std::string strFilePath = m_strConfigPath + "DataCfg/Debug/" + strConfigName;
#else
	std::string strFilePath = m_strConfigPath + "DataCfg/Release/" + strConfigName;
#endif

	GetFileContent(strFilePath, strContent);
	if (strContent.length() == 0)
	{
		printf("LoadPluginConfig Path = %s failed\n", strFilePath.c_str());
		return NULL;
	}

	void* pData = rkParser(strConfigName, strContent);
	it->second.existed = pData != NULL;

	return pData;
}

bool FragrantGrass::ConfigModule::GetFileContent(const std::string& strFileName, std::string& strContent)
{
	FILE* fp = fopen(strFileName.c_str(), "rb");
	if (!fp)
	{
		return false;
	}

	if (-1 == fseek(fp, 0, SEEK_END))
	{
		perror("PluginManager::GetFileContent fseek failed");
		fclose(fp);
		return false;
	}
	const long filelength = ftell(fp);
	if (-1 == fseek(fp, 0, SEEK_SET))
	{
		perror("PluginManager::GetFileContent fseek failed");
		fclose(fp);
		return false;
	}
	strContent.resize(filelength);
	size_t elementCnt = 1;
	size_t readCnt = fread((void*)strContent.data(), filelength, elementCnt, fp);
	if (readCnt != elementCnt)
	{
		perror("PluginManager::GetFileContent fread failed");
		fclose(fp);
		return false;
	}
	fclose(fp);

	return true;
}

void FragrantGrass::ConfigModule::RegisterFileParser(FileParseType type, FILE_PARSE_FUNCTION func, const std::string& name)
{
	ConfigData& config = m_fileParserMap[type];
	config.type = type;
	config.function = func;
	config.name = name;
	config.existed = false;
}

void* FragrantGrass::ConfigModule::FileParser_ServerDatas(const std::string& strFileName, std::string& strContent)
{
	if (strContent.length() > 0)
	{
		rapidxml::xml_document<> xDoc;
		xDoc.parse<0>((char*)strContent.c_str());
		std::string nodeName = "Server";
		rapidxml::xml_node<>* pRoot = xDoc.first_node();
		m_ServerInfoReportList.clear_server_list();

		for (rapidxml::xml_node<>* pServerNode = pRoot->first_node("Server"); pServerNode; pServerNode = pServerNode->next_sibling("Server"))
		{
			const char* strId = pServerNode->first_attribute("Id")->value();//such as MasterServer_1 MasterServer_2
			const char* strArea = pServerNode->first_attribute("Area")->value();//int value such as 1,2,3...
			const char* strCell = pServerNode->first_attribute("Cell")->value();//int value such as 1,2,3...
			const char* cpuCount = pServerNode->first_attribute("CpuCount")->value();//int value such as 1,2,3...
			const char* strIP = pServerNode->first_attribute("IP")->value();//IP such as 192.168.31.15
			const char* strMaxOnLine = pServerNode->first_attribute("MaxOnline")->value();//int value such as 5000,5555
			const char* strName = pServerNode->first_attribute("Name")->value();//such as DBServer MasterServer
			const char* strPort = pServerNode->first_attribute("Port")->value();//Port
			const char* strServerID = pServerNode->first_attribute("ServerID")->value();//ServerID
			const char* strType = pServerNode->first_attribute("Type")->value();//int value implement FG_SERVER_TYPES
			const char* strWSPort = pServerNode->first_attribute("WSPort")->value();//Port
			const char* strWebPort = pServerNode->first_attribute("WebPort")->value();//Port

			Protocol::ServerInfoReport* pServerData = m_ServerInfoReportList.add_server_list();
			Protocol::ServerInfoReport& serverData = (*pServerData);
			serverData.set_server_id(lexical_cast<int>(strServerID));
			serverData.set_server_name(strId);
			serverData.set_server_cur_count(0);
			serverData.set_server_ip(strIP);
			serverData.set_server_port(lexical_cast<int>(strPort));
			serverData.set_server_max_online(lexical_cast<int>(strMaxOnLine));
			serverData.set_server_state(Protocol::EST_NARMAL);
			serverData.set_server_type(lexical_cast<int>(strType));
			serverData.set_server_area(lexical_cast<int>(strArea));
		}
	}

	return &m_ServerInfoReportList;
}